package com.jml.controller;


import com.jml.SessionAttribute.SessionAttributeController;
import com.jml.SessionAttribute.PathVariableController;
import com.jml.注册校验器.InitBinder参数转换;
import com.jml.注册校验器.ModelAttributeController;
import com.jml.注册校验器.RequestBodyAdvice和ControllerAdvice;
import com.jml.注册校验器.User参数校验Validator;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.FrameworkServlet;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.servlet.http.HttpServletRequest;

public class 笔记 {

    /**
     *
     * 3个父子servlet的主要功能？：
     *  HttpServletBean：没有参与实际请求的处理。
     *  FrameworkServlet：将不同类型的请求合并到了processRequest方法统一处理， processRequest方法中做了三件事
     *      1.调用了DispatcherServlet的doService方法具体处理请求。
     *      2.将当前请求的 LocaleContext和ServletRequestAttributes在处理请求前设置到了LocaleContextHolder和RequestContextHolder，
     *      并在请求处理完成后恢复
     *      3.请求处理完后发布了ServletRequestHandledEvent消息。
     *  DispatcherServlet:doService方法给 request设置了一些属性并将请求交给 diSpatch方法具体处理。
     *      DispatcherServlet中的doDiSpatch方法完成 Spring MVC中请求处理过程的顶层设计，
     *      它使用 DispatcherServlet中的九大组件完成了具体的请求处理。
     */

    /**
     *FrameworkServlet的service -> HttpServlet的service -> FrameworkServlet的doGet ->processRequest ->DispatcherServlet的doService
     * {@link FrameworkServlet.doGet}
     *
     * 1.LocaleContextHolder和RequestContextHolder有什么用，里面保存什么东西？
     * 存放的local也就是本地化信息 比如zh-cn，一个是里面保存了request的全部参数。都保存在ThreadLocal中
     * 这样不管当前线程运行到哪一行代码都可以获取到当前线程的属性，request的所有属性和local
     */

    /**
     * {@link GoController#submit#showorders}
     * {@link DispatcherServlet#doService}
     *
     * 2.FlashMap涉及Request的三个属性作用，都是干什么的，常用的场景是什么?
     *
     *INPUT_FLASH_MAP_ATTRIBUTE是保存上次请求中转发过来的属性
     *OUTPUT_FLASH_MAP_ATTRIBUTE用来保存本次请求需要转发的属性
     *FLASH_MAP_MANAGER_ATTRIBUTE就是FlatMapManagement管理器，上面两个属性都是在这里管理的
     *
     *redirect本身是没有传递参数的功能的,按普通的模式如果想传递参数，就只能将其写人url中，
     *但是url有长度限制另外有些场景中我们想传递的参数还不想暴露在ur里，这时就可以用 flashMan的OUTPUT_FLASH_MAP_ATTRIBUTE来进行传递
     * ---------------------------------------------------------------------------------------------------------------
     * 通过RequestContextHolder放入属性：
     *          ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
     * 			HttpServletRequest request001 = requestAttributes.getRequest();
     * 			FlashMap f = (FlashMap)request001.getAttribute(DispatcherServlet.OUTPUT_FLASH_MAP_ATTRIBUTE);
     * 			f.put("name","张三丰");
     * 	通过RequestContextHolder获取属性：
     * 	        Map f =  request001.getAttribute(DispatcherServlet.INPUT_FLASH_MAP_ATTRIBUTE);
     * 			f.get("name");
     * ---------------------------------------------------------------------------------------------------------------
     * 	普通方式放入属性到FlatMap：
     * 	    RedirectAttributes attr
     * 	    attr.addFlashAttribute("ordersId","XXX");
     * 拼接到重定向的URL中
     * 	    attr.addAttribute("local","zh-cn");
     */

    /**
     *Handler：也就是处理器，它直接对应着MVC中的C也就是 Controller层，它的具体表现形式有很多，可以是类，也可以是方法，
     *      如果你能想到别的表现形式也可以使用，它的类型是 Object。
     *      我们前面例子中标注了@RequestMapping的所有方法都可以看成一个Handler。
     *      只要可以实际处理请求就可以是Handler
     *
     *HandlerMapping：是用来查找 Handler的，匹配Request和Handler
     *      在Spring MVc中会处理很多请求，每个请求都需要一个 Handler来处理，具体接收到一个请求后使用哪个 Handler来处理呢？这就是HandlerMapping要做的事情。
     *
     *HandlerAdapter：就是适配器。因为 Spring MVC中的 Handler可以是任意的形式，只要能处理请求就OK，
     *      但是 Servlet需要的处理方法的结构却是固定的，都是以request和response为参数的方法（如 doService方法）。
     *      但是我们的Handler的参数中不一定是request和response
     *      怎么让固定的 Servlet处理方法调用灵活的 Handler来进行处理呢？这就是 Handler Adapter要做的事情。
     *
     *View是用来展示数据的，而 View Resolver用来査找使用哪个view来展示数据。
     *      通俗地讲就是干完活后需要写报告，写报告又需要模板（比如，是调查报告还是验收报告或者是下一步工作的请示等），
     *      view就是所需要的模板，模板就像公文里边的格式，内容就是 Model里边的数据，
     *      View Resolver就是用来选择使用哪个模板的。
     * 现在再回过头去看上面的四句代码应该就觉得很容易理解了，它们分别是：使用HandlerMapping找到干活的 Handler，找到使用 Handler的 HandlerAdapter，
     * 让 HandlerAdapter使用 Handler干活，干完活后将结果写个报告交上去（通过vew展示给用户）。
     *
     *doDispatch中首先检查是不是上传请求，如果是上传请求，则将 request转换为 MultiparthttpServletrequest，
     * 	    并将multipartRequestParsed标志设置为tue。其中使用到了MultipartResolver
     *然后通过 getHandler方法获取 Handler处理器链，其中使用到了 HandlerMapping，返回值为 HandlerExecutionChain类型，
     *      其中包含着与当前request相匹配的Interceptor和Handler
     */

    /**
     * {@link DispatcherServlet#doDispatch}
     *  doDispatch的流程？：
     * 1.判断是否是上传请求如果不是上传请求则直接使用接收到的 request，否则request转换为 MultiparthttpServletrequest
     * 2.根据请求获取到处理器（里面是一个执行的数组，如果有拦截器就先执行拦截器的前置处理），
     * 3.根据处理器获取到处理器适配器
     * 4.处理Last_modifier的问题
     * 5.执行拦截器preHandler方法
     * 6用适配器调用处理器
     * 7.调用完毕后如果需要异步，就直接返回
     * 8.否则判断view，如果view为空设置默认的view
     * 9.执行拦截器postHandler方法
     * 10.渲染视图，调用拦截器的afterCompletion方法
     * 11.finally中如果是需要异步处理，调用异步处理拦截器，如果是长传文件的请求就清除上传过程中产生的临时文件
     */

    /**
     *spring mvc的9大组件
     *
     * HandlerMapping
     *
     * HandlerAdapter
     *
     * HanndlerExceptionResolver：这个组件是根据异常设置ModelAndView，之后在交给render方法进行渲染
     *      render只负责将ModedlAndView渲染成页面，具体M 是怎么来得到render并不关心。值处理请求过程中的异常，
     *      不管渲染视图中的产生的异常
     *
     *ViewResolver：根据viewName查找view
     *          用来将String类型的视图名（有的地方也叫逻辑视图，都指同一个东西）和Locale解析为View类型的视图，
     *          接口方法的参数是视图名和Locale不过一般情况我们只需要根据视图名找到对应的视图，然后渲染就行，并不需要对不同的区域使用不同视图进行显示，
     *          如果需要国际化支持也只要将显示的内容或者主题使用国际化支持，Spring Mvc确实有这个功能，可以让不同的区域使用不同的视图进行显示。
     *          ResourceBundleViewResolver就需要同时使用视图名和Locale来解析视图。
     *          ResourceBundleViewResolver需要将每一个视图名和对应的视图类型配置到相应的properties文件中，默认使用 classpath下的view为baseName的配置文件，如views.properties、views_zh_CN.properties等，
     *          basename和文件位置都可以设置。不同的Locale会使用不同的配置文件，而且它们之同没有任何关系，这样就可以让不同的区域使用不同的vieW来进行渲染了
     *          view是用来渲染页面的，通俗点说就是要将程序返回的参数填入模板里，生成html（也可能是其他类型）文件。这里有两个关键的问题口1.使用哪个模板？ 2.用什么技术（或者规则）填入参数？
     *          这其实就是ViewResolver主要要做的工作， ViewResolver需要找到渲染所用的模板和所用的技术（也就是视图的类型）进行渲染，
     *          具体的渲染过程则交给不同的视图自己完成。我们最常使用的 UrlBasedViewResolver系列的解析器都是针对单一视图类型进行解析的，只需要找到使用的模板就可以了，
     *          比如，InternalResourceViewResolver只针对jsp类型的视图，FreeMarkerViewResolver只针对FreeMarker, VelocityViewResolver只针对 Vacity.
     *
     * RequestToViewNameTranslator:ViewResolver是根据viewName查找view，但是Handler处理完毕后没有设置view和ViewName，
     *          此时就需要通过RequestToViewNameTranslator来从request获取viewName
     *          在springmvc中RequestToViewNameTranslator只能有一个，所以所有的request到ViewName的转换规则都在一个Translator中
     *
     *LocaleResolver:获取Locale
     *          解析视图需要两个参数：一个是视图名，另一个是 Locale。视图名是处理器返回的（或者使用 RequestToviewNameTranslator解析的默认视图名），
     *          LocaleResolver用于从 request解析出 Locale, Locale在前面已经介绍过，就是zh-cn之类，表示一个区域。
     *          有了这个就可以对不同区域的用户显示不同的结果，这就是i8n（国际化）的基本原理。
     *          在进入doService方法中就会设置LocaleResolver到request，我们可以直接从request中获取
     *          request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
     *
     *ThemeResolver：解析主题
     *
     * MultipartResolver:处理上传请求，
     *          处理方法是将普通的 request包装成 MultipartHttpServletrequest，后者可以直接调用 getFile方法获取到File，
     *          如果上传多个文件，还可以调用 getFileMap得到 FileName → File结构的Map，
     *          这样就使得上传请求的处理变得非常简单。
     *          当然，这里做的其实是锦上添花的事情，如果上传的请求不用 MultipartResolver封装成MultiparthttpServletrequest
     *          直接用原来的request也是可以的，所以在SpringMvc中此组件没有提供默认值。
     *
     * FlashMapManager:对重定向传递参数
     *
     *
     *
     */
    /**
     *HandlerMapping->AbstractHandlerMapping
     *                                      ->AbstractUrlHandlerMapping
     *                                      ->AbstractMethodHandlerMapping
     *AbstractHandlerMapping保存了所有的拦截器，子类方法getHandlerInternal获取Handler
     *
     */

    /**
     *在初始化RequestMappingHandlerMapping类的时候会建立Controller的各种url的映射关系放入RequestMappingHandlerMapping类的内部RegistryMapping中
     *      他的处理器一定是HandlerMethod类型，里面存放了controller类信息和方法信息
     *在初始化BeanNameUrlHandlerMapping的时候，因为他的父类实现了ApplicationContextAware接口，所以会调用setApplicationContext方法
     *      带有"/"开头的beanname都会放进AbstractUrlHandlerMapping的handleMap里面
     *在得到处理器的时候两种handlerMapping根据uri轮询查找，优先查找RequestMappingHandlerMapping，这种存放的是有controller注解的
     *      然后查找BeanNameUrlHandlerMapping，这种存放的是实现Controller接口的。
     */
    /**
     *HandlerAdapter:
     * ------>AbstractHandlerMethodAdapter
     * ------------>RequestMappingHandlerAdapter，只要是处理器满足是HandlerMethod类型就用这种
     * ------>HttpRequestHandlerAdapter只要是处理器满足HttpRequestHandler类
     * ------>SimpleControllerHandlerAdapter只要是处理器满足Controller类接口
     * ------>SimpleServletHandlerAdapter只要是处理器满足Servlet类
     */

    /**
     * 准备参数：
     *  参数来源有6个地方：
     *  1.request中的参数，url及其post个请求头中的信息
     *  2.cookie的参数
     *  3.session的参数
     *  4.设置到Flatmap的参数，主要是重定向传递
     *  5.SessionAttribute传递的参数，这种参数根据@SessionAttribute注解传递
     *  6.通过相应的注释了@ModelAttribute的方法进行设置参数
     *  参数的解析是通过不同的ArgumentResovler来解析
     */
    /**
     * @InitBinder,@ModelAttribute,@ControllerAdvice作用
     *
     * {@link InitBinder参数转换#initBinder}
     * {@link User参数校验Validator}
     * 在哪个controller设置了就会让哪个controller使用这些特性
     * 有@InitBinder注释的方法用于初始化Bind，可以对参数做校验，也可以对参数进行转换
     *
     *@ModelAttribute：在哪个controller设置了就会让哪个controller使用这些特性:
     * 注解在方法上就用于设置参数，会在执行处理前将参数设置到model中
     *      @ModelAttribute如果设置了value就将其设置为参数名，返回值作为参数设置到Model
     *      如果方法含有Model，Map，ModelMap类型的参数，则可以将直接需要的参数设置上去，
     *      如果既没有设置value也没有设置Model类型参数则根据返回值类型解析参数名
     *注解在参数上则需要指定的ArgumentResolver来解析参数
     *
     *@InitBinder,@ModelAttribute在哪个controller设置了就会让哪个controller使用这些特性，
     *      如果要全部生效最好定义一个基类，让所有的Controller都继承这个基类，但是如果有的Controller
     *      继承了其他的类，那么这个Controller就只能自己定义一份不能使用公共的，此时@ControllerAdvice可以解决这个问题
     *
     *@ControllerAdvice：
     * 定义一个类，类上面加@ControllerAdvice注解，然后把@InitBinder,@ModelAttribute注释的方法放进这个类中
     * 这样每个Handler都会调用@InitBinder,@ModelAttribute的特性。
     * 在springmvc4.0版本中@ControllerAdvice注解加了这几个属性：value,basePackages,basePackageClasses,assignableTypes,annotations
     *通过这些属性决定哪些Controller可以用，哪些Controller不用。
     * value是basePackages的别名表示配置的基础包，
     * basePackageClasses是basePackages的安全替代品，会扫描配置类所在包下的所有类
     *      比如设置了配置类：com.jml.user,就会扫描com.jml包下的所有类
     *assignableTypes,annotations分别指具体的类和类所含的注解
     *
     *{@link RequestBodyAdvice和ControllerAdvice}
     *{@link ModelAttributeController#RequestBodyAdvice}
     * ResponseBodyAdvice接口，这个类可以修改返回值直接作为ResponseBody类型的处理器返回值，有两种类型的处理器会将返回值设置为ResponseBody
     *      1.返回值为HttpEntity类型
     *      2.返回值前注有注解ResponseBody
     *      要想让生效必须注册到spring mvc的容器中
     *              1.直接注册到RequestMappingHandlerAdapter
     *              2.接口类上加注解@ControllerAdvice
     *
     */

    /**
     * RequestMappingHandlerAdapter的处理流程：
     *  1.解析参数的参数来源有多种大体分为两类：Model和Request
     *      Model是通过FlatMapManager和ModelFactory管理。
     *      不同类型的参数使用不同的参数解析器处理，
     *      有的Resolver使用了WebDataBinderFactory创建WebDataBinder，可以通过@InitBinder向WebDataBinderFactory中注册WebDataBinder
     *  2.执行请求用的HandlerMethod的子类ServletInvocableHandlerMethod(实际执行是InvocableHandlerMethod)
     *  3.返回值是使用HandlerMethodReturnValueHandler进行解析，不同类型的返回值使用不同的HandlerMethodReturnValueHandler
     *  4.整个过程ModelAndViewContainer起着参数传递的作用
     *
     *
     */

    /**
    *RequestMappingHandlerAdapter实现了InitializingBean接口，
     *     afterPropertiesSet主要初始化argumentResolvers--类型解析器,
     *     initBinderArgumentResolvers,returnValueHandlers
     *     以及@ControllerAdvise注解类相关的modelAttributeAdviceCache,initBinderAdviceCache和responseBodyAdvice这6个属性
     *     argumentResolvers：用于给处理器方法注释了@ModelAttribute的方法设置参数
     *     initBinderArgumentResolvers：用于给处理器方法注解了@InitBinder设置参数
     *     returnValueHandlers：用于给处理器返回值处理成ModelAndView类型
     *     modelAttributeAdviceCache和initBinderAdviceCache：分别用于缓存@ControllerAdvise注解类中的@ModelAttribute和@InitBinder注解的方法，也就是全局的方法
     *             每个处理器在第一次使用的时候会把他注解中的值缓存起来，这样之后再次调用的时候就不用再次查找这些方法而是直接从缓存中获取
     *     responseBodyAdvice：用来保存前面介绍过的实现了ResponseBodyAdvice接口，返回值被@ResponseBody修饰的
    */
    /**
     *参数解析器分为4中：
     *      1.按注解解析的，
     *      2.按照类型解析的，
     *      3.按照自定义参数类型解析的，
     *      4.可解析全部参数
     * 这个也是参数解析的顺序
     */
    /**
     * @SessionAttribute注解详解：
     *      注解在处理器上用于多个请求之间传递参数，类似于session的Attributr，但是不完全一样、
     *      @SessionAttribute 设置的参数只是暂时的传递而不是长期保存，比如身份验证的信息需要长期保存的应该放在session中
     *      @SessionAttribute注解设置的参数有三种用法：
     *          1.在视图中通过 request.getAttribute() 或者通过 session.getAttribute()获取
     *          2.在后面请求返回的视图中通过session.getAttribute()或者Model获取
     *          3.自动将参数设置到后面的请求所对应的处理器的Model类型参数或者有@ModelAttributr注解的参数中
     * {@link SessionAttributeController}
     *        这个类被@SessionAttributes注解修饰，他将会对名字是"book","description"的参数和类型是Double.class的参数使用
     *SessionAttribute来保存。所以在/sessionAttribute/index请求中将这三个参数设置到Model中，同时也会设置到SessionAttributes中
     * 这样在redirect后的getBySessionAttributes处理器方法中获取到，获取的方法使用@ModelAttribute和ModelMap两种方式，使用完毕后
     * 通过调用sessionStatus.setComplete();通知这个SessionAttributes已经使用完毕了，这时参数就从缓存中删除了，所以再次重定向到complete后
     * 在这个处理器方法中就获取不到了.
     *
     */

    /**
     * Redirect的参数校验：
     *  在处理器中如果要对一个参数进行校验只需要在前面加上@Valid或者@Validated注解即可，但是Redirect转发后校验结果就消失了
     * 因为是默认保存在ModelAndViewContainer的defaultModel中，而FlatMap只会传递redirectModel保存的参数，所以校验结果就会丢失
     *  传递校验参数的两个方法：
     * 1.通过SessionAttribute传递，只需要在处理上注解@SessionAttributes(type={BindingResult.class})即可，这样BindingResult类型的参数就会保存到SessionAttribute
     * 如果使用这种方法就一定要及时清理SessionAttributes就是设置Complete，否则会造成混乱
     *
     * 2.重新校验一遍，springMVC的参数校验在ModelAttributeMethodProcessor参数解析的时候判断有没有@Valid或者@Validated注解，如果有就校验
     * ModelAttributeMethodProcessor解析器用于解析注解了@ModelAttribute的参数和没注解的自定义参数，所以在redirect重定向到的目的处理器中
     * 将要校验的参数街道处理器的参数，并且加@Valid @Validate注解，这样不容易出错/
     * ModelAttributeMethodProcessor解析器在解析的时候会把校验结果放入到Model中
     */
    /**
     *bridge method介绍
     */
    /**
     *PathVariable和matrixVariable的使用方法
     * {@link PathVariableController}
     * PathVariable：
     *  1.参数解析的时候并不是按照uri中顺序解析的比如/student/{studentID}/book/{bookId}
     *  2.参数名和变量名不同也可以解析，只要求注解中的名字和uri中名字一样即可。如果里面没有设置值，那么默认的值就是参数名。
     *matrixVariable：
     *  matrixVariable也是url中的参数，但是他不是url两个斜杠中的值，而是值的属性通过分号或者逗号设置
     *  比如：
     *       uri是：/matrixVariable/student/zhangsan;sex=男;group=gg
     *       //如果只有一个属性就按照定义的变量名字和url中属性的名字一样进行赋值。
     *       @RequestMapping(value = "/matrixVariable/student/{studentName}", method = RequestMethod.GET)
     *       public void getStudentAndSexAndGroup(@PathVariable("studentName") String studentName,
     *                                            @MatrixVariable String sex,
     *                                            @MatrixVariable String group)
     *       这种情况MatrixVariable中的值默认是必填的，我们可以设置为非必填或者设置默认值@MatrixVariable(required=false)
     *
     *@MatrixVariable也可以是数组：
     * 比如：
     *      uri是：/matrixVariable/student/zhangsan;colors=black,red/tel/1881307;group=gg
     *      //如果只有一个属性就按照定义的变量名字和url中属性的名字一样进行赋值。
     *     @RequestMapping(value = "/matrixVariable/student/{studentName}/tel/{telName}",method = RequestMethod.GET)
     *     public void getStudentAndSexAndGroup001(@PathVariable("studentName") String studentName,
     *                                          @PathVariable("telName") String telName,
     *                                          @MatrixVariable(required = false) Set<String> colors,
     *                                          @MatrixVariable(required=false) String gender,
     *                                          @MatrixVariable(required=false) String group){
     *         System.out.println(studentName);//zhangsan
     *         System.out.println(telName);    //1881307
     *         System.out.println(colors);     //black,red
     *         System.out.println(gender);     //null
     *         System.out.println(group);      //gg
     *     }
     *
     * 如果不同的值存在相同的属性：
     *      比如：group有两个，是不同的值中的属性
     *      // uri是：/matrixVariable/student/zhangsan;colors=black,red;group=note/tel/1881307;group=gg
     *      //url中不同的值假如有一样的属性，可以使用pathVar指定是哪个值再使用value指定是这个值的哪个属性，
     *      //@MatrixVariable(required=false,pathVar = "studentName",value = "group") String namGroup --表示是studentName中的group属性
     *      //@MatrixVariable(required=false,pathVar = "telName",value = "group") String group --表示是telName中的group属性
     *      //如果只有一个属性就按照定义的变量名字和url中属性的名字一样进行赋值。
     *     @RequestMapping(value = "/matrixVariable/student/{studentName}/tel/{telName}",method = RequestMethod.GET)
     *     public void getStudentAndSexAndGroup002(@PathVariable("studentName") String studentName,
     *                                             @PathVariable("telName") String telName,
     *                                             @MatrixVariable(required = false) Set<String> colors,
     *                                             @MatrixVariable(required=false) String gender,
     *                                             @MatrixVariable(required=false,pathVar = "studentName",value = "group") String namGroup,
     *                                             @MatrixVariable(required=false,pathVar = "telName",value = "group") String group){
     *         System.out.println(studentName);//zhangsan
     *         System.out.println(telName);    //1881307
     *         System.out.println(colors);     //black,red
     *         System.out.println(gender);     //null
     *         System.out.println(group);      //gg
     *     }
     *@MatrixVariable也可以是Map：
     *  比如：
     *     // uri是：/matrixVariable/student/zhangsan;colors=black,red;group=note/tel/1881307;group=gg;sex=mm
     *     @RequestMapping(value = "/matrixVariable/student/{studentName}/tel/{telName}",method = RequestMethod.GET)
     *     public void getStudentAndSexAndGroupMap(@PathVariable("studentName") String studentName,
     *                                             @PathVariable("telName") String telName,
     *                                             //上面所有的属性都放在一个Map
     *                                             @MatrixVariable Map<String,String> matrixVars,
     *                                             //把studentName的属性放在一个Map
     *                                             @MatrixVariable(pathVar = "studentName") Map<String ,String> matrixVarsStudentName,
     *                                             //把telName的属性放在一个Map
     *                                             @MatrixVariable(pathVar = "telName") Map<String ,String> matrixVarsTelName){
     *         System.out.println(studentName);            //zhangsan
     *         System.out.println(telName);                //1881307
     *         System.out.println(matrixVars);             // { colors:[black,red] , group:[note,gg] , sex:mm}
     *         System.out.println(matrixVarsStudentName);  // { colors:[black,red] , group:note }
     *         System.out.println(matrixVarsTelName);      // { group:gg , sex:mm}
     *     }
     *在springMvc中如果要使用MatrixVariable，需要把{@link RequestMappingHandlerMapping}中的setRemoveSemicolonContent设置为false，
     *      如果使用mvc:annotation-driven可以简单的通过<mvc:mvc:annotation-driven enable-matrix-variables="true"/>设置
     *      RemoveSemicolonContent用于表示是否删除url中分号相关的内容，作用是防止注入
     *
     */
    /**
     *存放所有的BeanDefinition{@link DefaultListableBeanFactory#beanDefinitionMap}
     * 存放所有的key{@link DefaultListableBeanFactory#beanDefinitionNames}
     *
     *
     *存放一个BD就会从alreadyCreated中移出一个同样的key
     *
     *
     *
     *
     *
     *
     */

    /**
     * 添加拦截器,进行断点调试
     */

}
